//  Copyright (C) 2012-2013 Alexander Alimov
//
//	This file is part of Lodestar library.
//
//		Lodestar library is free software: you can redistribute it and/or modify
//		it under the terms of the GNU Lesser General Public License as published by
//		the Free Software Foundation, either version 3 of the License, or
//		(at your option) any later version.
//
//		Lodestar library is distributed in the hope that it will be useful,
//		but WITHOUT ANY WARRANTY; without even the implied warranty of
//		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//		GNU Lesser General Public License for more details.
//
//		You should have received a copy of the GNU Lesser General Public License
//		along with Lodestar library.  If not, see <http://www.gnu.org/licenses/>.
#ifndef LODESTAR_STEERING_H
#define LODESTAR_STEERING_H

#include "geometry.h"

namespace lodestar
{
    /**
     * Interface for simple vehicle.
     */
    class LODESTAR_API IVehicle
    {
    public:
        virtual ~IVehicle() {}

        virtual float getMass() const = 0;
        virtual void setMass(float value) = 0;

        /**
         * Gets current position of vehicle.
         *
         * @return  The position in meters.
         */
        virtual Vector getPosition() const = 0;

        /**
         * Gets current velocity of vehicle.
         *
         * @return  The velocity in meters per second.
         */
        virtual Vector getVelocity() const = 0;

        /**
         * Gets the maximum speed that engine can produce.
         * Total speed can be much more than this value.
         *
         * @return  The maximum speed.
         */
        virtual float getMaxSpeed() const = 0;

        /**
         * Applies a force to vehicle.
         *
         * @param   force   The force to apply.
         */
        virtual void applyForce( const Vector& force) = 0;

        /**
         * Applies the steering velocity to vehicle.
         *         Use it for kinematic model.
         *
         * @param   steering    The steering velocity. Should me not greater than maximum speed
         */
        virtual void applySteering(const Vector& steering) = 0;

        virtual void setAngle(float angle) = 0;
    };

    /**
     * Interface for all steerings.
     */
    class LODESTAR_API ISteering
    {
    public:
        virtual ~ISteering() {}
        virtual Vector getSteering() = 0;
    };

    class LODESTAR_API SeekSteering : public ISteering
    {
    public:
        virtual Vector getSteering() override;
        bool init(IVehicle* vehicle, const Vector& target);
    protected:
        IVehicle*   mVehicle;
        Vector      mTarget;
    };

    class LODESTAR_API FleeSteering : public ISteering
    {
    public: 
        virtual Vector getSteering() override;
    protected:
        IVehicle*   mVehicle;
        Vector      mTarget;
    };

    class LODESTAR_API PursuitSteering : public ISteering
    {
    public: 
        virtual Vector getSteering() override;
    protected:
        IVehicle*   mVehicle;
        IVehicle*   mTarget;
    };

    class LODESTAR_API OffsetPursuitSteering : public ISteering
    {

    };

    class LODESTAR_API EvasionSteering : public ISteering
    {
    public: 
        virtual Vector getSteering() override;
    protected:
        IVehicle*   mVehicle;
        IVehicle*   mTarget;
    };

    class LODESTAR_API ArrivalSteering : public ISteering
    {
    public: 
        virtual Vector getSteering() override;

        bool init(IVehicle* vehicle, const Vector& target, float distance);
    protected:
        IVehicle*   mVehicle;
        Vector      mTarget;
        float mSlowingDistance;
    };

    class LODESTAR_API ObstacleAvoidanceSteering : public ISteering
    {
    public: 
        virtual Vector getSteering() override;
    protected:
        IVehicle*   mVehicle;
    };

    class LODESTAR_API WanderSteering : public ISteering
    {
    public: 
        virtual Vector getSteering() override;
    protected:
        IVehicle*   mVehicle;
    };

    class LODESTAR_API ExploreSteering : public ISteering
    {
    public: 
        virtual Vector getSteering() override;
    };

    class LODESTAR_API PathFollowingSteering : public ISteering
    {
    public: 
        virtual Vector getSteering() override;
    };
    
    class LODESTAR_API WheightedSteering : public ISteering
    {
    public:
        virtual Vector getSteering() override;
    protected:
        struct SteeringComponent
        {
            float       wheight;
            ISteering*  steering;

            SteeringComponent* next;
        };

        SteeringComponent* mSteerings;
    };

    class LODESTAR_API PrioritizedDithering : public ISteering
    {
    public:
        virtual Vector getSteering() override;
    };
}
#endif